//
// how to run burnpipe in a single graph

#include "burnpipe.h"
#include <thread>

using burn::CStatus;
using burn::GElementPtr;
using burn::GPipelineFactory;
using burn::GPipelinePtr;

struct MyParam : public burn::GParam {
  burn::CVoid reset(const CStatus &curStatus) override { iValue = 0; }

  int iValue{0};
  int iCount{0};
};

class MyNode1 : public burn::GNode {
public:
  CStatus run() override {
    CStatus status;
    burn::CGRAPH_ECHO(
        "[%s], enter MyNode1 run function. Sleep for 1 second ... ",
        this->getName().c_str());
    CGRAPH_SLEEP_SECOND(1)
    return status;
  }
};

class MyNode2 : public burn::GNode {
public:
  CStatus init() override {
    CStatus status;
    burn::CGRAPH_ECHO("[%s], enter MyNode2 init function.",
                      this->getName().c_str());
    return status;
  }

  CStatus run() override {
    CStatus status;
    burn::CGRAPH_ECHO(
        "[%s], enter MyNode2 run function. Sleep for 2 second ... ",
        this->getName().c_str());
    CGRAPH_SLEEP_SECOND(2)
    return status;
  }

  CStatus destroy() override {
    CStatus status;
    burn::CGRAPH_ECHO("[%s], enter MyNode2 destroy function.",
                      this->getName().c_str());
    return status;
  }
};

void tutorial_simple() {
  GPipelinePtr pipeline = GPipelineFactory::create();
  GElementPtr a, b, c, d = nullptr;

  CStatus status = pipeline->registerGElement<MyNode1>(&a, {}, "nodeA");
  status += pipeline->registerGElement<MyNode2>(&b, {a}, "nodeB");
  status += pipeline->registerGElement<MyNode1>(&c, {a}, "nodeC");
  status += pipeline->registerGElement<MyNode2>(&d, {b, c}, "nodeD");
  if (!status.isOK()) {
    return;
  }

  status += pipeline->init();

  for (int i = 0; i < 3; i++) {
    status += pipeline->run();
    burn::CGRAPH_ECHO(
        "==== tutorial_simple, loop : [%d], and run status = [%d].", i + 1,
        status.getCode());
  }

  status += pipeline->destroy();
  GPipelineFactory::remove(pipeline);
}

int main() {
  tutorial_simple();
  return 0;
}